package tiandang.core.service.impl;

import com.alibaba.druid.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tiandang.core.dao.*;
import tiandang.core.error.BusinessException;
import tiandang.core.error.EmBusinessError;
import tiandang.core.model.*;
import tiandang.core.service.OrderService;
import tiandang.core.service.ProductService;
import tiandang.core.service.ProductStockService;
import tiandang.core.validator.ValidationResult;
import tiandang.core.validator.ValidatorImpl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class OrderServiceImpl implements OrderService {

  @Autowired
  private OrderMapper orderMapper;

  @Autowired
  private PromoMapper promoMapper;

  @Autowired
  private ManagerMapper managerMapper;

  @Autowired
  private OrderProductMapper orderProductMapper;

  @Autowired
  private ProductMapper productMapper;

  @Autowired
  private ProductService productService;

  @Autowired
  private SequenceInfoMapper sequenceInfoMapper;

  @Autowired
  private ValidatorImpl validator;

  @Autowired
  private ProductStockService productStockService;


  @Override
  public Object getList(Long startTimestamp, Long endTimestamp, String managerName,
                        String productName, Integer deliveryStatus, String orderId, Integer currentPage, Integer limit) {

    Map<String, Object> map = new HashMap<>();
    List<OrderInfo> orderList = new ArrayList<>();
    int offset = (currentPage - 1) * limit;
    int totalCount = 0;

    //开团开始时间和结束时间不为空
    if (startTimestamp != null && endTimestamp != null) {
      orderList = orderMapper.getListByPromoTime(startTimestamp, endTimestamp, limit, offset);
      totalCount = orderMapper.countByPromoTime(startTimestamp, endTimestamp);

      if (orderList.size() > 0) {
        orderList = addOrderRelative(orderList);
      }

      map.put("orderList", orderList);
      map.put("totalCount", totalCount);
      return map;
    }

    //团长名字不为空
    if (!StringUtils.isEmpty(managerName)) {
      orderList = orderMapper.getListByManagerName(managerName, limit, offset);
      totalCount = orderMapper.countByManagerName(managerName);

      if (orderList.size() > 0) {
        orderList = addOrderRelative(orderList);
      }

      map.put("orderList", orderList);
      map.put("totalCount", totalCount);
      return map;
    }

    //商品名称不为空
    if (!StringUtils.isEmpty(productName)) {
      orderList = orderMapper.getListByProductName(productName, limit, offset);
      totalCount = orderMapper.countByProductName(productName);

      if (orderList.size() > 0) {
        orderList = addOrderRelative(orderList);
      }
      map.put("orderList", orderList);
      map.put("totalCount", totalCount);
      return map;
    }

    if (deliveryStatus != null) {
      orderList = orderMapper.getListByDeliveryStatus(deliveryStatus, limit, offset);
      totalCount = orderMapper.countByDeliveryStatus(deliveryStatus);

      if (orderList.size() > 0) {
        orderList = addOrderRelative(orderList);
      }

      map.put("orderList", orderList);
      map.put("totalCount", totalCount);
      return map;
    }

    if (!StringUtils.isEmpty(orderId)) {
      OrderInfo order = orderMapper.selectByPrimaryKey(orderId);
      if (order != null) {
        orderList.add(order);
        totalCount = 1;
      }

      if (orderList.size() > 0) {
        orderList = addOrderRelative(orderList);
      }

      map.put("orderList", orderList);
      map.put("totalCount", totalCount);
      return map;
    }

    //获取全部订单数据
    orderList = orderMapper.getListByPage(limit, offset);
    totalCount = orderMapper.countAllOrders();

    if (orderList.size() > 0) {
      orderList = addOrderRelative(orderList);
    }

    map.put("orderList", orderList);
    map.put("totalCount", totalCount);
    return map;
  }

  private List<OrderInfo> addOrderRelative(List<OrderInfo> orderList) {
    //加上开团对象;团长对象
    for (OrderInfo order : orderList) {
      Promo promo = promoMapper.selectByPrimaryKey(order.getPromoId());
      order.setPromo(promo);

      Manager manager = managerMapper.selectByPrimaryKey(order.getManagerId());
      order.setManager(manager);
    }

    return orderList;
  }

  @Override
  public OrderInfo getOrderById(String orderId) {
    OrderInfo order = orderMapper.selectByPrimaryKey(orderId);
    Promo promo = promoMapper.selectByPrimaryKey(order.getPromoId());
    order.setPromo(promo);

    Manager manager = managerMapper.selectByPrimaryKey(order.getManagerId());
    order.setManager(manager);

    List<OrderProduct> orderProductList = orderProductMapper.getListByOrderId(order.getId());
    order.setOrderProductList(orderProductList);
    return order;
  }

  @Override
  @Transactional
  public synchronized OrderInfo createOrder(OrderInfo order) throws BusinessException {
    //校验入参
    ValidationResult validateResult = validator.validate(order);
    if (validateResult.isHasErrors()) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, validateResult.getErrMsg());
    }

    //校验开团信息
    Promo promo = promoMapper.selectByPrimaryKey(order.getPromoId());
    if (promo == null) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "团购不存在");
    }
    Long now = new Date().getTime();
    if (promo.getStartTimestamp() > now) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "团购未开始");
    } else if (promo.getEndTimestamp() < now) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "团购已结束");
    }


    //openid 长度 28位
    if (order.getOpenid().length() != 28) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "用户信息错误");
    }


    //1.校验下单状态:下单的商品是否存在,用户是否合法,购买数量是否正确
    List<OrderProduct> orderProductList = order.getOrderProductList();

    if (orderProductList == null || orderProductList.size() == 0) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "商品信息错误");
    }

    for (OrderProduct orderProduct : orderProductList) {
      if (orderProduct.getProductNumber() <= 0 || orderProduct.getProductNumber() > 99) {
        throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "商品数量信息错误");
      }
    }

    //对比商品清单的数量和查询结果的数量是否一致,如果一致,说明商品都存在
    //在查询商品的库存,所有商品库存足够才能下单
    int total = 0;
    List<Integer> productIdList = new ArrayList<>();
    for (OrderProduct orderProduct : orderProductList) {
      total += orderProduct.getProductNumber();
      productIdList.add(orderProduct.getProductId());
    }

    List<Product> productList = productMapper.getListByIdList(productIdList);
    if (orderProductList.size() != productList.size()) {
      throw new BusinessException(EmBusinessError.PARAMMETER_VALIDATION_ERROR, "商品信息错误");
    }


    ProductStock productStock;
    for (OrderProduct orderProduct : orderProductList) {
      productStock = productStockService.getProductStockByProductId(orderProduct.getProductId());
      if (productStock.getStock() < orderProduct.getProductNumber()) {
        throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH);
      }
    }

    //落单减库存
    productService.decreaseStock(orderProductList);

    BigDecimal originAmount = new BigDecimal(0);
    BigDecimal orderAmount = new BigDecimal(0);
    for (OrderProduct orderProduct : orderProductList) {
      for (Product product : productList) {
        if (orderProduct.getProductId().intValue() == product.getId().intValue()) {
          originAmount = originAmount.add(product.getOriginPrice().multiply(new BigDecimal(orderProduct.getProductNumber())));
          orderAmount = orderAmount.add(product.getPresentPrice().multiply(new BigDecimal(orderProduct.getProductNumber())));
        }
      }
    }

    //订单入库
    String orderNo = generateOrderNo();
    order.setId(orderNo);
    order.setOriginAmount(originAmount);
    order.setOrderAmount(orderAmount);
    order.setTotal(total);
    orderMapper.insertSelective(order);

    //购买的商品入库
    for (OrderProduct orderProduct : orderProductList) {
      for (Product product : productList) {
        if (orderProduct.getProductId().intValue() == product.getId().intValue()) {
          orderProduct.setOrderId(orderNo);
          orderProduct.setName(product.getName());
          orderProduct.setOriginPrice(product.getOriginPrice());
          orderProduct.setPresentPrice(product.getPresentPrice());
          orderProduct.setImgUrl(product.getImgUrl());
          orderProductMapper.insertSelective(orderProduct);
        }
      }
    }

    //加上商品的销量
    productService.increaseSales(orderProductList);

    return order;
  }

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  private String generateOrderNo() {
    StringBuilder stringBuilder = new StringBuilder();
    //16位,前8位为时间信息,年月日
    LocalDateTime now = LocalDateTime.now();
    String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-", "");
    stringBuilder.append(nowDate);
    //中间6位为自增序列
    //获取当前sequence
    int sequence = 0;
    SequenceInfo sequenceInfo = sequenceInfoMapper.getSequenceByName("order_info");
    sequence = sequenceInfo.getCurrentValue();
    sequenceInfo.setCurrentValue(sequenceInfo.getCurrentValue() + sequenceInfo.getStep());
    sequenceInfoMapper.updateByPrimaryKeySelective(sequenceInfo);

    String sequenceStr = String.valueOf(sequence);
    for (int i = 0; i < 6 - sequenceStr.length(); i++) {
      stringBuilder.append(0);
    }
    stringBuilder.append(sequenceStr);

    return stringBuilder.toString();
  }

  @Override
  @Transactional
  public void refund(String id) throws BusinessException {
    List<OrderProduct> orderProductList = orderProductMapper.getListByOrderId(id);

    //减去团长被冻结的佣金
    List<Integer> productIdList = new ArrayList<>();
    for (OrderProduct orderProduct : orderProductList) {
      productIdList.add(orderProduct.getProductId());
    }

    List<Product> productList = productService.getListByProductIdList(productIdList);
    BigDecimal rewardTotal = new BigDecimal(0);
    for (OrderProduct orderProduct : orderProductList) {
      for (Product product : productList) {
        if (orderProduct.getProductId().intValue() == product.getId().intValue()) {
          //佣金 = 商品单价x团长佣金百分比x商品数量
          BigDecimal proportion = new BigDecimal(product.getProportion()).divide(new BigDecimal(100));
          rewardTotal = rewardTotal.add(product.getPresentPrice().multiply(proportion)
            .multiply(new BigDecimal(orderProduct.getProductNumber())));
        }
      }
    }

    OrderInfo order = orderMapper.selectByPrimaryKey(id);
    managerMapper.minusFrozenReward(order.getManagerId(), rewardTotal);

    //减去开团总收入
    promoMapper.minusIncomeAmount(order.getPromoId(), order.getOrderAmount());

    //加库存
    productService.increaseStock(orderProductList);

    //减去商品的销量
    productService.decreaseSales(orderProductList);
  }

  @Override
  public void deliverProduct(String id) {
    orderMapper.deliverProduct(id);
  }

  @Override
  public List<OrderProduct> getOrderProductListByOrderId(String orderId) {
    return orderProductMapper.getListByOrderId(orderId);
  }

  @Override
  public List<OrderInfo> getListByPromoId(Integer promoId) {
    return orderMapper.getListByPromoId(promoId);
  }

  @Override
  public void updatePayStatusByOrderId(String orderId) {
    orderMapper.updatePayStatusByOrderId(orderId);
  }

  @Override
  public Object getListByOpenid(String openid, Integer currentPage, Integer limit) {
    Map<String, Object> map = new HashMap<>();
    int offset = (currentPage - 1) * limit;
    List<OrderInfo> orderList = orderMapper.getListByOpenid(openid, limit, offset);
    for (OrderInfo orderInfo : orderList) {
      List<OrderProduct> orderProductList = orderProductMapper.getListByOrderId(orderInfo.getId());
      orderInfo.setOrderProductList(orderProductList);
    }
    int totalCount = orderMapper.countByOpenid(openid);

    int totalPage;
    if (totalCount % limit == 0) {
      totalPage = totalCount / limit;
    } else {
      totalPage = (totalCount / limit) + 1;
    }
    map.put("orderList", orderList);
    map.put("totalCount", totalCount);
    map.put("totalPage", totalPage);
    return map;
  }

  @Override
  public List<OrderInfo> getUnPayOrder() {
    return orderMapper.getUnPayOrder();
  }

  @Override
  public void updateOrderStatus(String orderId, Integer orderStatus) {
    orderMapper.updateOrderStatus(orderId, orderStatus);
  }

  @Override
  public List<OrderInfo> getPayedAndCancelStatusOrder() {
    return orderMapper.getPayedAndCancelStatusOrder();
  }

}
